﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Web;
using System.Configuration;
using IrendilDLL.Database;
using System.IO;
using System.Data;

namespace IrendilDLL.utilities
{
    /// <summary>
    /// Classe che implementa tutti i metodi di calcoli/statistiche 
    /// sull'utilizzo dei dischi
    /// </summary>
    public class DisksStatistic
    {
        /// <summary>
        /// Costruttore di default
        /// </summary>
        public DisksStatistic()
        {
            // Procedo solo se é correttamente inizializzata la variabile di sessione
            installationGUID = (String)HttpContext.Current.Session["installationGUID"];

            // Ottengo la stringa di connessione al db
            localSqlServerStr = ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString;

            // Istanzio la classe di appoggio per il db di irendil
            irendilDbManager = new IrendilDbManager(localSqlServerStr);
            // Istanzio la classe di appoggio per il db
            dbManager = new DataBaseManager(localSqlServerStr);
        }

        /// <summary>
        /// Guid installazione di riferimento
        /// </summary>
        String installationGUID = null;
        /// <summary>
        /// Stringa di connessione al db
        /// </summary>
        string localSqlServerStr = null;
        /// <summary>
        /// Riferimento al file di log
        /// </summary>
        TextWriter logFile;
        /// <summary>
        /// Istanta di appoggio alla classe gestione db
        /// </summary>
        DataBaseManager dbManager = null;
        /// <summary>
        /// Istanta di appoggio alla classe gestione db di irendil
        /// </summary>
        IrendilDbManager irendilDbManager = null;

        /// <summary>
        /// Metoto che fa un'analisi e calcolo statistico in base allo storico dei giorni rimanenti per il volume passato
        /// </summary>
        /// <param name="guidHost">host di riferimeno</param>
        /// <param name="volume">disco di riferimento</param>
        /// <param name="size">dimensione del disco</param>
        /// <param name="freespace">spazio libero</param>
        /// <returns>Ritorna il num di giorni rimanenti. -1 in caso di impossibilità di calcolo</returns>
        public int calculateRemainingDays(Guid guidHost, String volume, double size, double freespace)
        {
            try
            {
                int remainingDays = -1;

                // Ricavo da DB gli eventuali valori presenti di storico dischi
                int backTime = 90;
                
                // Imposto i parametri per la QUERY
                SqlParameter[] parameters = new SqlParameter[3];
                parameters[0] = new SqlParameter("@GUIDHost", guidHost);
                parameters[1] = new SqlParameter("@Volume", volume);
                parameters[2] = new SqlParameter("@backTime", backTime);

                // Apro la transazione, eseguo la store e la chiudo
                dbManager.OpenTransaction();
                DataSet hostDs = dbManager.EseguiStored("sp_getDisksHistory", parameters);
                dbManager.CloseTransaction();

                // indice del numero di campioni utilizzati
                int samples = 0;

                // Controllo che ci sia un dataset
                if (hostDs != null && hostDs.Tables.Count > 0)
                {
                    // Ottengo il DataTable
                    DataTable hostDt = hostDs.Tables[0];
                    // Controllo che il dataTable non sia vuoto
                    if (hostDt.Rows.Count > 0)
                    {
                        double tmp = 0;
                        // Ciclo su tutti gli elementi del datatable
                        for (int i = 0; i < hostDt.Rows.Count; i++)
                        {
                            //freespaceieri - freespaceoggi / ieriDelta + freespacel'altroieri-freespaceogg/delataaltroieri
                            tmp += (Convert.ToDouble(hostDt.Rows[i]["FreeSpace"]) - freespace) / Convert.ToInt32(hostDt.Rows[i]["DeltaDays"]);
                            samples++;
                        }

                        double spaceForDay = (tmp / samples);
                        double remainingDaysFloat = freespace / spaceForDay;

                        // Cotrollo gli estremi prima di fare CAST ********
                        if (remainingDaysFloat >= Int32.MaxValue)
                            remainingDaysFloat = Int32.MaxValue;

                        if (remainingDaysFloat < 1 && remainingDaysFloat > 0)
                            remainingDaysFloat = 0;

                        if (remainingDaysFloat < 0)
                            remainingDaysFloat = Int32.MaxValue;

                        if (Double.IsNaN(remainingDaysFloat))
                            remainingDaysFloat = -1;

                        if (Double.IsPositiveInfinity(remainingDaysFloat))
                            remainingDaysFloat = Int32.MaxValue;

                        if (Double.IsNegativeInfinity(remainingDaysFloat))
                            remainingDaysFloat = 0;
                        //**************************************************

                        remainingDays = Convert.ToInt32(remainingDaysFloat);
                        
                        // Se i giorni rimanenti sono superiori a circa 30 anni tronco la stima li
                        //if (remainingDays < 10000)
                        //    return remainingDays;
                        //else
                        //    return 10000;

                        return remainingDays;
                    }
                    else
                        return -1;
                }
                else
                    return -1;

            }
            catch (Exception ex)
            {
                // Istanzio la classe di gestione dell'errore
                LogErrors logError = new LogErrors(); 
                // Scrivo l'errore su file
                logError.WriteLogToFile(ex.Source+": "+ex.Message);
                // Rimbalzo l'eccezione per la visualizzazione su gui
                throw ex;
            }

        }
    }
}
